package org.jeecg.modules.online.cgform.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.util.*;
import org.jeecg.modules.online.cgform.enhance.CgformEnhanceJavaInter;
import org.jeecg.modules.online.cgform.enhance.CgformEnhanceJavaListInter;
import org.jeecg.modules.online.cgform.entity.*;
import org.jeecg.modules.online.cgform.enums.CgformEnum;
import org.jeecg.modules.online.cgform.mapper.*;
import org.jeecg.modules.online.cgform.model.OnlCgformModel;
import org.jeecg.modules.online.cgform.model.OnlGenerateModel;
import org.jeecg.modules.online.cgform.service.IOnlCgformFieldService;
import org.jeecg.modules.online.cgform.service.IOnlCgformHeadService;
import org.jeecg.modules.online.cgform.service.IOnlCgformIndexService;
import org.jeecg.modules.online.cgform.util.CgformUtil;
import org.jeecg.modules.online.config.exception.BusinessException;
import org.jeecg.modules.online.config.exception.DBException;
import org.jeecg.modules.online.config.model.CgformConfigModel;
import org.jeecg.modules.online.config.model.DataBaseConfig;
import org.jeecg.modules.online.config.service.DbTableHandleI;
import org.jeecg.modules.online.config.util.DataBaseConst;
import org.jeecg.modules.online.config.util.DbTableProcess;
import org.jeecg.modules.online.config.util.DbTableUtil;
import org.jeecgframework.codegenerate.database.DbReadTableUtil;
import org.jeecgframework.codegenerate.generate.impl.CodeGenerateOne;
import org.jeecgframework.codegenerate.generate.impl.CodeGenerateOneToMany;
import org.jeecgframework.codegenerate.generate.pojo.ColumnVo;
import org.jeecgframework.codegenerate.generate.pojo.TableVo;
import org.jeecgframework.codegenerate.generate.pojo.onetomany.MainTableVo;
import org.jeecgframework.codegenerate.generate.pojo.onetomany.SubTableVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: Online表单开发
 * @Author: jeecg-boot
 * @Date: 2019-03-12
 * @Version: V1.0
 */
@Slf4j
@Service("onlCgformHeadServiceImpl")
public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, OnlCgformHead> implements IOnlCgformHeadService {

	@Autowired
	private IOnlCgformFieldService fieldService;
	
	@Autowired
	private IOnlCgformIndexService indexService;
	
	@Autowired
	private OnlCgformEnhanceJsMapper onlCgformEnhanceJsMapper;
	
	@Autowired
	private OnlCgformButtonMapper onlCgformButtonMapper;
	
	@Autowired
	private OnlCgformEnhanceJavaMapper onlCgformEnhanceJavaMapper;
	
	@Autowired
	private OnlCgformEnhanceSqlMapper onlCgformEnhanceSqlMapper;
	
	@Autowired
	private DataBaseConfig dataBaseConfig;
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Result<?> addAll(OnlCgformModel model) {

		String uuid = UUID.randomUUID().toString().replace("-", "");

		OnlCgformHead head = model.getHead();
		List<OnlCgformField> fields = model.getFields();
		List<OnlCgformIndex> indexs = model.getIndexs();

		head.setId(uuid);

		for (int i = 0; i < fields.size(); i++) {
			OnlCgformField field = fields.get(i);
			field.setId(null);
			field.setCgformHeadId(uuid);
			if (field.getOrderNum() == null) {
				field.setOrderNum(i);
			}
			specialFieldHandler(field);
		}

		for (OnlCgformIndex index : indexs) {
			index.setId(null);
			index.setCgformHeadId(uuid);
		}
		
		//update-begin-author:每个数据库设置的默认值不一样 导致数据显示异常,此处java代码写死
		head.setIsDbSynch("N");
		head.setTableVersion(1);
		//update-end-author:每个数据库设置的默认值不一样 导致数据显示异常,此处java代码写死

		head.setCopyType(0);
		//update-begin-author:taoyan date:20190923 for:如果不设置排序序号 默认设置为1 issue #524
		if(head.getTableType()==3 && head.getTabOrderNum()==null) {
			head.setTabOrderNum(1);
		}
		//update-end-author:taoyan date:20190923 for:如果不设置排序序号 默认设置为1 issue #524
		super.save(head);
		fieldService.saveBatch(fields);
		indexService.saveBatch(indexs);
		
		//添加一张表 需要处理是否有主表信息
		handleMainTableInfo(head, fields);

		return Result.ok("添加成功");
	}

	

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Result<?> editAll(OnlCgformModel model) {
		OnlCgformHead head = model.getHead();

		OnlCgformHead headEntity = super.getById(head.getId());
		if (headEntity == null) {
			return Result.error("未找到对应实体");
		}
		String isDbSync = headEntity.getIsDbSynch();
		if(CgformUtil.databaseTableIsChange(headEntity, head)) {
			isDbSync = "N";
		}
		// table version 自增1
		Integer version = headEntity.getTableVersion();
		if (version == null) {
			version = 1;
		}
		head.setTableVersion(++version);

		List<OnlCgformField> fields = model.getFields();
		List<OnlCgformIndex> indexs = model.getIndexs();

		// 将fields分类成 添加和修改 两个列表
		List<OnlCgformField> addFields = new ArrayList<OnlCgformField>();
		List<OnlCgformField> editFields = new ArrayList<OnlCgformField>();
		for (OnlCgformField field : fields) {
			String id = String.valueOf(field.getId());
			specialFieldHandler(field);
			if (id.length() == 32) {
				// 修改项
				editFields.add(field);
			} else {
				// id 不做修改
				String primaryKey = "_pk";
				if (!primaryKey.equals(id)) {
					// 新增项
					field.setId(null);
					field.setCgformHeadId(head.getId());
					addFields.add(field);
				}
			}
		}
		if(addFields.size()>0) {
			isDbSync = "N";
		}
		int maxOrderNum = 0;
		// 批量修改
		for (OnlCgformField field : editFields) {
			OnlCgformField dbField = this.fieldService.getById(field.getId());
			boolean ischange = CgformUtil.databaseFieldIsChange(dbField, field);
			if(ischange) {
				isDbSync = "N";
			}
			if((dbField.getOrderNum()==null?0:dbField.getOrderNum())>maxOrderNum) {
				maxOrderNum = dbField.getOrderNum();
			}
			fieldService.updateById(field);
		}
		//fieldService.saveBatch(addFields);
		for (OnlCgformField  onlCgformField: addFields) {
			if (onlCgformField.getOrderNum() == null) {
				onlCgformField.setOrderNum(++maxOrderNum);
			}
			fieldService.save(onlCgformField);
		}

		// 将item Index 分类
		List<OnlCgformIndex> dbCgformIndex = indexService.getCgformIndexsByCgformId(head.getId());
		List<OnlCgformIndex> addIndex = new ArrayList<OnlCgformIndex>();
		List<OnlCgformIndex> editIndex = new ArrayList<OnlCgformIndex>();
		for (OnlCgformIndex index : indexs) {
			String id = String.valueOf(index.getId());
			if (id.length() == 32) {
				// 修改项
				editIndex.add(index);
			} else {
				// 新增项
				index.setId(null);
				index.setCgformHeadId(head.getId());
				addIndex.add(index);
			}
		}

		//删除索引配置(通过逻辑删除字段记录删除状态，方便同步数据库的时候删除索引)
		for (OnlCgformIndex index : dbCgformIndex) {
			boolean bool = indexs.stream().anyMatch(a -> index.getId().equals(a.getId()));
			if(!bool){
				index.setDelFlag(CommonConstant.DEL_FLAG_1);
				editIndex.add(index);
				isDbSync = "N";
			}
		}

		if(addIndex.size()>0) {
			isDbSync = "N";
			indexService.saveBatch(addIndex);
		}

		for (OnlCgformIndex index : editIndex) {
			OnlCgformIndex dbIndex = this.indexService.getById(index.getId());
			boolean ischange = CgformUtil.databaseIndexIsChange(dbIndex, index);
			if(ischange) {
				isDbSync = "N";
				index.setIsDbSynch("N");
			}
			indexService.updateById(index);
		}

		// 删除项
		if (model.getDeleteFieldIds().size() > 0) {
			isDbSync = "N";
			fieldService.removeByIds(model.getDeleteFieldIds());
		}
//		采用del_flag标记删除，不直接物理删除数据
//		if (model.getDeleteIndexIds().size() > 0) {
//			isDbSync = "N";
//			indexService.removeByIds(model.getDeleteIndexIds());
//		}

		head.setIsDbSynch(isDbSync);
		super.updateById(head);
		
		handleMainTableInfo(head, fields);
		
		handleCopyTableColumns(head,fields);
		
		return Result.ok("全部修改成功");
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void doDbSynch(String code,String synMethod) throws HibernateException, IOException, TemplateException, SQLException, DBException {
		//1.判断实体配置
		OnlCgformHead onlCgformHead = this.getById(code);
		if(onlCgformHead==null) {
			throw new DBException("实体配置不存在");
		}
		String tbname = onlCgformHead.getTableName();
		//2.查询字段集合
		LambdaQueryWrapper<OnlCgformField> query = new LambdaQueryWrapper<OnlCgformField>();
		query.eq(OnlCgformField::getCgformHeadId, code);
		query.orderByAsc(OnlCgformField::getOrderNum);
		
		List<OnlCgformField> fieldList =  fieldService.list(query);
		//3.构造同步参数CgformConfigModel实例
		CgformConfigModel model = new CgformConfigModel();
		model.setTableName(tbname);
		model.setJformPkType(onlCgformHead.getIdType());
		model.setJformPkSequence(onlCgformHead.getIdSequence());
		model.setContent(onlCgformHead.getTableTxt());
		model.setColumns(fieldList);
		model.setDbConfig(dataBaseConfig);
		//4.判断是否普通同步
		if (CgformUtil.SYNC_NORMAL.equals(synMethod)) {
			long startTime = System.currentTimeMillis();
			boolean isExist = DbTableUtil.judgeTableIsExit(tbname);
			log.info("==判断表是否存在消耗时间"+ (System.currentTimeMillis()-startTime)+"毫秒");
			//判断数据库表是否存在 
			if(isExist) {
				//step.1 表字段变更处理
				DbTableProcess process = new DbTableProcess();
				List<String> list = process.updateTable(model);
				for (String sql : list) {
					if(oConvertUtils.isEmpty(sql)||oConvertUtils.isEmpty(sql.trim())) {
						continue;
					}
					this.baseMapper.executeDDL(sql);
				}

				//===========================================================================================================================================
				//step.2 表索引变更处理
				//表已存在 那么就先删除索引
				List<OnlCgformIndex> configIndexList = indexService.list(new LambdaQueryWrapper<OnlCgformIndex>().eq(OnlCgformIndex::getCgformHeadId, code));
				//update-begin-author:taoyan date:20190826 for：不能删除不存在的索引 ，删除前判断一下
				for (OnlCgformIndex configIndex : configIndexList) {
					if("N".equals(configIndex.getIsDbSynch()) || CommonConstant.DEL_FLAG_1.equals(configIndex.getDelFlag())){
						String countIndexSql = process.getCountIndexSql(configIndex.getIndexName(), tbname);
						if(indexService.isExistIndex(countIndexSql)){
							String delIndexSql = process.dropIndex(configIndex.getIndexName(), tbname);
							try {
								log.info("删除索引 executeDDL:"+ delIndexSql);
								this.baseMapper.executeDDL(delIndexSql);
								//删除索引后，将逻辑删除数据，从物理表里删除
								if(CommonConstant.DEL_FLAG_1.equals(configIndex.getDelFlag())){
									indexService.removeById(configIndex.getId());
								}
							} catch (Exception e) {
								log.error("删除表【"+tbname+"】索引("+configIndex.getIndexName()+")失败!",e);
							}
						}else{
							//库中无索引，则将逻辑删除数据，从物理表里删除
							if(CommonConstant.DEL_FLAG_1.equals(configIndex.getDelFlag())){
								indexService.removeById(configIndex.getId());
							}
						}
					}
				}
				//update-end-author:taoyan date:20190826 for：不能删除不存在的索引 ，删除前判断一下
				//===========================================================================================================================================
			}else {
				DbTableProcess.createTable(model);
				
			}
		}else if (CgformUtil.SYNC_FORCE.equals(synMethod)) {
			//强制同步，先删除后添加
			DbTableHandleI handler = DbTableUtil.getTableHandle();
			String sql = handler.dropTableSQL(tbname);
			this.baseMapper.executeDDL(sql);
			DbTableProcess.createTable(model);
		}
		
		//处理完表 再处理索引
		indexService.createIndex(code, DbTableUtil.getDatabaseType(),tbname);
		
		//同步完成 修改同步标识
		onlCgformHead.setIsDbSynch("Y");
		this.updateById(onlCgformHead);
	}

	@Override
	public void deleteRecordAndTable(String id) throws DBException, SQLException {
		OnlCgformHead onlCgformHead = this.getById(id);
		if(onlCgformHead==null) {
			throw new DBException("实体配置不存在");
		}
		long startTime = System.currentTimeMillis();
		boolean isExist = DbTableUtil.judgeTableIsExit(onlCgformHead.getTableName());
		log.info("==判断表是否存在消耗时间 "+ (System.currentTimeMillis()-startTime)+"毫秒");
		if(isExist){
			String sql = DbTableUtil.getTableHandle().dropTableSQL(onlCgformHead.getTableName());
			log.info(" 删除表  executeDDL： "+ sql);
			this.baseMapper.executeDDL(sql);
		}
		this.baseMapper.deleteById(id);
		this.deleteSubTableConfig(onlCgformHead);
	}

	@Override
	public void deleteRecord(String id) throws DBException, SQLException {
		OnlCgformHead onlCgformHead = this.getById(id);
		if(onlCgformHead==null) {
			throw new DBException("实体配置不存在");
		}
		this.baseMapper.deleteById(id);
		this.deleteSubTableConfig(onlCgformHead);
	}

	/**
	 * 删除子表 需要关联删除主表的subTableStr
	 * @param onlCgformHead
	 */
	private void deleteSubTableConfig(OnlCgformHead onlCgformHead){
		if(onlCgformHead.getTableType()==3){
			//只有附表才需要处理此处逻辑
			LambdaQueryWrapper query = new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId,onlCgformHead.getId());
			List<OnlCgformField> list = this.fieldService.list(query);
			String mainTableName = null;
			//1.先找到主表名称
			for (OnlCgformField field : list) {
				mainTableName = field.getMainTable();
				break;
			}
			if(oConvertUtils.isNotEmpty(mainTableName)){
				OnlCgformHead mainTable = baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName,mainTableName));
				if(mainTable!=null){
					//2.再找到主表 SubTableStr 进行剔除
					String str = mainTable.getSubTableStr();
					if(oConvertUtils.isNotEmpty(str)){
						List<String> strList = Arrays.asList(str.split(",")).stream().collect(Collectors.toList());
						strList.remove(onlCgformHead.getTableName());
						mainTable.setSubTableStr(String.join(",",strList));
						this.baseMapper.updateById(mainTable);
					}
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Map<String, Object>> queryListData(String sql){
		return this.baseMapper.queryList(sql);

	}

	@Override
	public void saveEnhance(OnlCgformEnhanceJs onlCgformEnhanceJs) {
		this.onlCgformEnhanceJsMapper.insert(onlCgformEnhanceJs);
	}

	@Override
	public OnlCgformEnhanceJs queryEnhance(String code,String type) {
		return this.onlCgformEnhanceJsMapper.selectOne(new LambdaQueryWrapper<OnlCgformEnhanceJs>().eq(OnlCgformEnhanceJs::getCgJsType , type).eq(OnlCgformEnhanceJs::getCgformHeadId , code));
	}

	@Override
	public void editEnhance(OnlCgformEnhanceJs onlCgformEnhanceJs) {
		this.onlCgformEnhanceJsMapper.updateById(onlCgformEnhanceJs);
		
	}

	@Override
	public OnlCgformEnhanceSql queryEnhanceSql(String formId,String buttonCode) {
		return this.onlCgformEnhanceSqlMapper.selectOne(new LambdaQueryWrapper<OnlCgformEnhanceSql>().eq(OnlCgformEnhanceSql::getCgformHeadId, formId).eq(OnlCgformEnhanceSql::getButtonCode, buttonCode));
	}

	@Override
	public void saveEnhance(OnlCgformEnhanceSql onlCgformEnhanceSql) {
		onlCgformEnhanceSqlMapper.insert(onlCgformEnhanceSql);
		
	}

	@Override
	public void editEnhance(OnlCgformEnhanceSql onlCgformEnhanceSql) {
		onlCgformEnhanceSqlMapper.updateById(onlCgformEnhanceSql);
		
	}

	@Override
	public OnlCgformEnhanceJava queryEnhanceJava(OnlCgformEnhanceJava onlCgformEnhanceJava) {
		LambdaQueryWrapper<OnlCgformEnhanceJava> query = new LambdaQueryWrapper<OnlCgformEnhanceJava>();
		query.eq(OnlCgformEnhanceJava::getButtonCode,onlCgformEnhanceJava.getButtonCode());
		query.eq(OnlCgformEnhanceJava::getCgformHeadId,onlCgformEnhanceJava.getCgformHeadId());
		query.eq(OnlCgformEnhanceJava::getCgJavaType,onlCgformEnhanceJava.getCgJavaType());
		query.eq(OnlCgformEnhanceJava::getEvent,onlCgformEnhanceJava.getEvent());
		return this.onlCgformEnhanceJavaMapper.selectOne(query);
	}

	@Override
	public void saveEnhance(OnlCgformEnhanceJava onlCgformEnhanceJava) {
		this.onlCgformEnhanceJavaMapper.insert(onlCgformEnhanceJava);
		
	}

	@Override
	public void editEnhance(OnlCgformEnhanceJava onlCgformEnhanceJava) {
		this.onlCgformEnhanceJavaMapper.updateById(onlCgformEnhanceJava);		
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OnlCgformButton> queryButtonList(String code,boolean isListButton) {
		LambdaQueryWrapper<OnlCgformButton> query = new LambdaQueryWrapper<OnlCgformButton>();
		query.eq(OnlCgformButton::getButtonStatus, "1");
		query.eq(OnlCgformButton::getCgformHeadId, code);
		if(isListButton) {
			query.in(OnlCgformButton::getButtonStyle, "link","button");
		}else {
			query.eq(OnlCgformButton::getButtonStyle, "form");
		}
		query.orderByAsc(OnlCgformButton::getOrderNum);
		return this.onlCgformButtonMapper.selectList(query);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<OnlCgformButton> queryButtonList(String code) {
		LambdaQueryWrapper<OnlCgformButton> query = new LambdaQueryWrapper<OnlCgformButton>();
		query.eq(OnlCgformButton::getButtonStatus, "1");
		query.eq(OnlCgformButton::getCgformHeadId, code);
		query.orderByAsc(OnlCgformButton::getOrderNum);
		return this.onlCgformButtonMapper.selectList(query);
	}

	@Override
	public boolean checkOnlyEnhance(OnlCgformEnhanceJava onlCgformEnhanceJava) {
		LambdaQueryWrapper<OnlCgformEnhanceJava> query = new LambdaQueryWrapper<OnlCgformEnhanceJava>();
		query.eq(OnlCgformEnhanceJava::getButtonCode,onlCgformEnhanceJava.getButtonCode());
		query.eq(OnlCgformEnhanceJava::getCgformHeadId,onlCgformEnhanceJava.getCgformHeadId());
		//query.eq(OnlCgformEnhanceJava::getCgJavaType,onlCgformEnhanceJava.getCgJavaType());
		//query.eq(OnlCgformEnhanceJava::getEvent,onlCgformEnhanceJava.getEvent());
		Integer count = this.onlCgformEnhanceJavaMapper.selectCount(query);
		if(count!=null) {
			if(count==1 && oConvertUtils.isEmpty(onlCgformEnhanceJava.getId())) {
				return false;
			}else if(count==2) {
				return false;
			}
		}
		return true;
	}

	@Override
	public List<String> queryOnlinetables() {
		return this.baseMapper.queryOnlinetables();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveDbTable2Online(String tbname) {
		OnlCgformHead cgFormHead = new OnlCgformHead();
		cgFormHead.setTableType(1);
		cgFormHead.setIsCheckbox("Y");
		cgFormHead.setIsDbSynch("Y");
		cgFormHead.setIsTree("N");
		cgFormHead.setIsPage("Y");
		cgFormHead.setQueryMode("group");
		cgFormHead.setTableName(tbname.toLowerCase());
		cgFormHead.setTableTxt(tbname);//TODO 能不能获取表的备注信息
		cgFormHead.setTableVersion(1);
		cgFormHead.setFormTemplate("1");//默认一列展示
		cgFormHead.setCopyType(0);
		cgFormHead.setScroll(1);//默认滚动条-有
		cgFormHead.setThemeTemplate("normal");//默认主题模板
		String cgFormId = UUIDGenerator.generate();
		cgFormHead.setId(cgFormId);
		List<OnlCgformField> columnsList = new ArrayList<OnlCgformField>();
		try {
			List<ColumnVo> list = DbReadTableUtil.b(tbname);
			for (int k = 0; k < list.size(); k++) {
				ColumnVo columnt = list.get(k);
				log.info("  columnt : "+ columnt.toString());
				String fieldName = columnt.getFieldDbName();
				OnlCgformField cgFormField = new OnlCgformField();
				cgFormField.setCgformHeadId(cgFormId);
				cgFormField.setDbFieldNameOld(columnt.getFieldDbName().toLowerCase());
				cgFormField.setDbFieldName(columnt.getFieldDbName().toLowerCase());
						
				if (oConvertUtils.isNotEmpty(columnt.getFiledComment())) {
					cgFormField.setDbFieldTxt(columnt.getFiledComment());
				} else {
					cgFormField.setDbFieldTxt(columnt.getFieldName());
				}
				
				cgFormField.setDbIsKey(0);
				cgFormField.setIsShowForm(1);
				cgFormField.setIsQuery(0);
				cgFormField.setFieldMustInput("0");
				cgFormField.setIsShowList(1);
				cgFormField.setOrderNum(k + 1);
				cgFormField.setQueryMode("single");
				cgFormField.setDbLength(oConvertUtils.getInt(columnt.getPrecision()));
				cgFormField.setFieldLength(120);
				cgFormField.setDbPointLength(oConvertUtils.getInt(columnt.getScale()));
				cgFormField.setFieldShowType("text");
				cgFormField.setDbIsNull("Y".equals(columnt.getNullable())?1:0);
				cgFormField.setIsReadOnly(0);
				
				if("id".equalsIgnoreCase(fieldName)){
					String[] pkTypeArr = {"java.lang.Integer","java.lang.Long"};
					String idFiledType = columnt.getFieldType();
					if(Arrays.asList(pkTypeArr).contains(idFiledType)){
						//如果主键是数字类型,则设置为自增长
						cgFormHead.setIdType("NATIVE");
					}else{
						//否则设置为UUID
						cgFormHead.setIdType("UUID");
					}
					cgFormField.setDbIsKey(1);
					cgFormField.setIsShowForm(0);
					cgFormField.setIsShowList(0);
					cgFormField.setIsReadOnly(1);
				}
				if ("java.lang.Integer".equalsIgnoreCase(columnt.getFieldType())){
					cgFormField.setDbType(DataBaseConst.INT);
				}else if ("java.lang.Long".equalsIgnoreCase(columnt.getFieldType())) {
					cgFormField.setDbType(DataBaseConst.INT);
				} else if ("java.util.Date".equalsIgnoreCase(columnt.getFieldType())) {
					cgFormField.setDbType(DataBaseConst.DATE);
					cgFormField.setFieldShowType("date");
				} else if ("java.lang.Double".equalsIgnoreCase(columnt.getFieldType())
						||"java.lang.Float".equalsIgnoreCase(columnt.getFieldType())) {
					cgFormField.setDbType(DataBaseConst.DOUBLE);
				} else if ("java.math.BigDecimal".equalsIgnoreCase(columnt.getFieldType()) || "BigDecimal".equalsIgnoreCase(columnt.getFieldType())) {
					cgFormField.setDbType(DataBaseConst.BIGDECIMAL);
				} else if ("byte[]".equalsIgnoreCase(columnt.getFieldType()) || columnt.getFieldType().contains("blob")) {
					cgFormField.setDbType(DataBaseConst.BLOB);
					columnt.setCharmaxLength(null);
                    //update-begin--Author:scott----  Date:20190924 ----for：Postgresql数据库导入表单,字段Text类型匹配问题解决----
				} else if ("java.lang.Object".equals(columnt.getFieldType()) && ("text".equalsIgnoreCase(columnt.getFieldDbType()) ||"ntext".equalsIgnoreCase(columnt.getFieldDbType()) ) ) {
					cgFormField.setDbType(DataBaseConst.TEXT);
					cgFormField.setFieldShowType(DataBaseConst.TEXTAREA);
                    //update-end--Author:scott----  Date:20190924 ----for：Postgresql数据库导入表单,字段Text类型匹配问题解决----
				}else if ("java.lang.Object".equals(columnt.getFieldType()) && "image".equalsIgnoreCase(columnt.getFieldDbType())) {
					cgFormField.setDbType(DataBaseConst.BLOB);
					//update-end--Author:scott----  Date:20190924 ----for：Postgresql数据库导入表单,字段Text类型匹配问题解决----
				} else {
					cgFormField.setDbType(DataBaseConst.STRING);
				}
				if (oConvertUtils.isEmpty(columnt.getPrecision()) && oConvertUtils.isNotEmpty(columnt.getCharmaxLength())) {
					if (Long.valueOf(columnt.getCharmaxLength()) >= 3000) {
						cgFormField.setDbType(DataBaseConst.TEXT);
						cgFormField.setFieldShowType(DataBaseConst.TEXTAREA);
						try{//有可能长度超出int的长度
							cgFormField.setDbLength(Integer.valueOf(columnt.getCharmaxLength()));
						}catch(Exception e){
							log.error(e.getMessage(), e);
						}
					} else {
						cgFormField.setDbLength(Integer.valueOf(columnt.getCharmaxLength()));
					}
				} else {
					if (oConvertUtils.isNotEmpty(columnt.getPrecision())) {
						cgFormField.setDbLength(Integer.valueOf(columnt.getPrecision()));
					}
					else{
						if(cgFormField.getDbType().equals(DataBaseConst.INT)){
							cgFormField.setDbLength(10);
						}
					}
					if (oConvertUtils.isNotEmpty(columnt.getScale())) {
						cgFormField.setDbPointLength(Integer.valueOf(columnt.getScale()));
					}

				}

				//update-begin--Author:scott----  Date:20200416 ----for：sqlserver数据库导入表单,字段nvarchar(max)类型db长度-1问题----
				if(oConvertUtils.getInt(columnt.getPrecision()) ==-1 && oConvertUtils.getInt(columnt.getScale())==0){
					cgFormField.setDbType(DataBaseConst.TEXT);
				}
				//update-end--Author:scott----  Date:20200416 ----for：sqlserver数据库导入表单,字段nvarchar(max)类型db长度-1问题-----
				//update-begin--Author:scott----  Date:20200416 ----for：大字段长度和精度统一设置为零----
				if(DataBaseConst.BLOB.equals(cgFormField.getDbType()) || DataBaseConst.TEXT.equals(cgFormField.getDbType()) || DataBaseConst.DATE.equals(cgFormField.getDbType())){
					cgFormField.setDbLength(0);
					cgFormField.setDbPointLength(0);
				}
				//update-end--Author:scott----  Date:20200416 ----for：大字段长度和精度统一设置为零----

				columnsList.add(cgFormField);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		if(oConvertUtils.isEmpty(cgFormHead.getFormCategory())){
			cgFormHead.setFormCategory("bdfl_include");
		}
		
		//保存表 字段 索引信息 
		//TODO 话说索引信息去哪里了
		this.save(cgFormHead);
		this.fieldService.saveBatch(columnsList);
		
	}
	
	/**
	 * 若当前为子表 需要同步主表的SubTableStr字段
	 * @param head
	 * @param fields
	 */
	private void handleMainTableInfo(OnlCgformHead head, List<OnlCgformField> fields) {
		//1.判断子表类型
		if(head.getTableType()==3) {
			head = this.baseMapper.selectById(head.getId());
			for (int i = 0; i < fields.size(); i++) {
				//2.遍历子表字段 拿到字段的外键配置
				OnlCgformField field = fields.get(i);
				String tbName = field.getMainTable();
				if(oConvertUtils.isEmpty(tbName)) {
					continue;
				}
				//3.拿到外键表名 获取主表信息
				OnlCgformHead mainTable = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tbName));
				if(mainTable==null) {
					continue;
				}
				
				//4.拿到主表SubTableStr 和当前这个做排序楼
				String allSubTable = mainTable.getSubTableStr();
				if(oConvertUtils.isEmpty(allSubTable)) {
					allSubTable = head.getTableName();
				}else {
					//TODO 这边应该对所有子表做一个排序
					if(allSubTable.indexOf(head.getTableName())>=0) {
						//如果当前这个子表字符串 包含当前子表 直接无视
						
					}else {
						//否则遍历、排序、加入
						@SuppressWarnings("unchecked")
						List<String> arr = new ArrayList(Arrays.asList(allSubTable.split(",")));
						for(int k=0;k<arr.size();k++) {
							String tempTbname = arr.get(k);
							OnlCgformHead tempTable = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tempTbname));
							if(tempTable==null) {
								continue;
							}
							if(head.getTabOrderNum()<oConvertUtils.getInt(tempTable.getTabOrderNum(),0)) {
								arr.add(k, head.getTableName());
								break;
							}
						}
						if(arr.indexOf(head.getTableName())<0) {
							arr.add(head.getTableName());
						}
						allSubTable = String.join(",", arr);
					}
				}
				mainTable.setSubTableStr(allSubTable);
				this.baseMapper.updateById(mainTable);
				break;
			}
		}else{
            //update-begin--Author:scott----  Date:20190925 ----for：TASK #3191 【online表单】一对多，附表改成单表，去掉关联后，主表sub_table_str字段还存在附表名---
            //由附表变为普通表单情况，判断是否在主表中存在附表配置，有的话则去掉该
            List<OnlCgformHead> mainTableList = this.baseMapper.selectList(new LambdaQueryWrapper<OnlCgformHead>().like(OnlCgformHead::getSubTableStr, head.getTableName()));
            if (mainTableList != null && mainTableList.size() > 0) {
                for (OnlCgformHead h : mainTableList) {
                    String subTableStr = h.getSubTableStr();
                    if (h.getSubTableStr().equals(head.getTableName())) {
                        subTableStr = "";
                    } else if (h.getSubTableStr().startsWith(head.getTableName() + ",")) {
                        subTableStr = subTableStr.replace(head.getTableName() + ",", "");
                    } else if (h.getSubTableStr().endsWith("," + head.getTableName())) {
                        subTableStr = subTableStr.replace("," + head.getTableName(), "");
                    } else if (h.getSubTableStr().indexOf("," + head.getTableName() + ",") != -1) {
                        subTableStr = subTableStr.replace("," + head.getTableName() + ",", ",");
                    }
                    h.setSubTableStr(subTableStr);
                    this.baseMapper.updateById(h);
                }
            }
            //update-end--Author:scott----  Date:20190925 ----for：TASK #3191 【online表单】一对多，附表改成单表，去掉关联后，主表sub_table_str字段还存在附表名---
        }
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveManyFormData(String code, JSONObject json,String xAccessToken) throws DBException, BusinessException {
		OnlCgformHead head = this.getById(code);
		if (head == null) {
			throw new DBException("数据库主表ID["+code+"]不存在");
		}
		//执行java增强 事件类型start
		String currButtonCode = "add";
		this.executeEnhanceJava(currButtonCode,"start", head, json);
		
		//json.put("id", UUIDGenerator.generate());
		String tbname = CgformUtil.getRealTableName(head.getTableName());
		if(head.getTableType()==2) {
			//如果他是主表 则还需要保存子表的数据
			String subTables = head.getSubTableStr();
			// 判断一下防止空指针
			if(oConvertUtils.isNotEmpty(subTables)){
				String[] arr = subTables.split(",");
				for (String tb : arr) {

					JSONArray jsonArray = json.getJSONArray(tb);
					if(jsonArray==null || jsonArray.size()==0) {
						continue;
					}

					OnlCgformHead temp = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tb));
					if(temp==null) {
						continue;
					}

					List<OnlCgformField> subFieldList = this.fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, temp.getId()));
					//这里有一步非常重要 需要获取子表字段对应设置外键的那个字段然后赋值
					String sublinkField="",subLinkValue=null;
					for (OnlCgformField field : subFieldList) {
						if(oConvertUtils.isEmpty(field.getMainField())) {
							continue;
						}
						sublinkField = field.getDbFieldName();
						String mainField = field.getMainField();

						//update-begin-author:taoyan date:20190924 for:主子表关联字段取值bug
						if(json.get(mainField.toLowerCase())!=null){
							subLinkValue = json.getString(mainField.toLowerCase());
						}
						if(json.get(mainField.toUpperCase())!=null){
							subLinkValue = json.getString(mainField.toUpperCase());
						}
						//update-end-author:taoyan date:20190924 for:主子表关联字段取值bug
					}

					for(int i=0;i<jsonArray.size();i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						if(subLinkValue!=null) {
							jsonObject.put(sublinkField, subLinkValue);//设置外键值
						}
						this.fieldService.saveFormData(subFieldList, tb, jsonObject);
					}
				}
			}

		}
		
		//如果是tree则 新增时 赋值：是否子节点
		if("Y".equals(head.getIsTree())) {
			this.fieldService.saveTreeFormData(code, tbname, json, head.getTreeIdField(), head.getTreeParentIdField());
		}else {
			this.fieldService.saveFormData(code, tbname, json,false);
		}
		//执行sql 增强
		this.executeEnhanceSql(currButtonCode, code, json);
		//执行java 增强 事件类型end
		this.executeEnhanceJava(currButtonCode,"end", head, json);

		//update-begin--- author:scott---date:20200313------for:移动OA统一草稿箱功能（online表单+设计器表单）,在保存表单时，判断关联流程的话则往流程中间表插入表单数据------------
		// 执行流程草稿保存
		// TODO 待优化
		if (oConvertUtils.isNotEmpty(json.get(DataBaseConstant.BPM_STATUS_TABLE)) || oConvertUtils.isNotEmpty(json.get(DataBaseConstant.BPM_STATUS_TABLE.toUpperCase()))) {
			try {
				// 请求 header
				HttpHeaders headers = new HttpHeaders();
				headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_JSON_UTF8_VALUE));
				headers.set("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
				headers.set("X-Access-Token", xAccessToken);
				//请求参数
				JSONObject entity = new JSONObject();
				entity.put("flowCode","onl_"+head.getTableName());
				entity.put("id",json.get("id"));
				entity.put("formUrl","modules/bpm/task/form/OnlineFormDetail");
				entity.put("formUrlMobile","online/OnlineDetailForm");
				String url = RestUtil.getBaseUrl() + "/process/extActProcess/saveMutilProcessDraft";
				JSONObject res = RestUtil.request(url, HttpMethod.POST, headers, null, entity, JSONObject.class).getBody();
				if (res != null) {
					String dataId = res.getString("result");
					log.info("保存流程草稿 dataId : " + dataId);
				}
			} catch (Exception e) {
				log.error("保存流程草稿异常, "+e.getMessage(),e);
			}
		}
		//update-end--- author:scott---date:20200313------for:移动OA统一草稿箱功能（online表单+设计器表单）,在保存表单时，判断关联流程的话则往流程中间表插入表单数据------------
		
	}

	@Override
	public Map<String, Object> querySubFormData(String table, String mainId) throws DBException {
		Map<String, Object> map = new HashMap<String, Object>();
		OnlCgformHead head = this.getOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName,table));
		if (head == null) {
			throw new DBException("数据库子表["+table+"]不存在");
		}
		List<OnlCgformField> subFieldList = this.fieldService.queryFormFields(head.getId(),false);
		String sublinkField=null;
		for (OnlCgformField field : subFieldList) {
			if(oConvertUtils.isNotEmpty(field.getMainField())) {
				sublinkField = field.getDbFieldName();
				break;
			}
		}
		List<Map<String, Object>> subList = this.fieldService.querySubFormData(subFieldList, table, sublinkField, mainId);
		if(subList!=null && subList.size()==0) {
			throw new DBException("数据库子表["+table+"]未找到相关信息,主表ID为"+mainId);
		}else if(subList.size()>1){
			throw new DBException("数据库子表["+table+"]存在多条记录,主表ID为"+mainId);
		}else {
			map=subList.get(0);
		}
		return map;
	}

	/** 查询子表所有的数据 */
	@Override
	public List<Map<String, Object>> queryManySubFormData(String table, String mainId) throws DBException {
		OnlCgformHead head = this.getOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName,table));
		if (head == null) {
			throw new DBException("数据库子表["+table+"]不存在");
		}
		List<OnlCgformField> subFieldList = this.fieldService.queryFormFields(head.getId(),false);
		String sublinkField=null;
		for (OnlCgformField field : subFieldList) {
			if(oConvertUtils.isNotEmpty(field.getMainField())) {
				sublinkField = field.getDbFieldName();
				break;
			}
		}
		List<Map<String, Object>> subList = this.fieldService.querySubFormData(subFieldList, table, sublinkField, mainId);
		if(subList!=null && subList.size()==0) {
			throw new DBException("数据库子表["+table+"]未找到相关信息,主表ID为"+mainId);
		} else {
			List<Map<String, Object>> result = new ArrayList<Map<String,Object>>(subList.size());
			for (Map<String, Object> map : subList) {
				result.add(CgformUtil.transLowerCaseMapKey(map));
			}
			return result;
		}
	}
	
	
	@Override
	public Map<String, Object> queryManyFormData(String code, String id) throws DBException {
		OnlCgformHead head = this.getById(code);
		if (head == null) {
			throw new DBException("数据库主表ID["+code+"]不存在");
		}
		List<OnlCgformField> fieldList = this.fieldService.queryFormFields(code,true);
		Map<String, Object> map = this.fieldService.queryFormData(fieldList, head.getTableName(), id);
		if(head.getTableType()==2) {
			//如果他是主表 则还需要查询子表的数据 查询子表数据 需找到关联字段赋值
			String subTables = head.getSubTableStr();
			if(oConvertUtils.isNotEmpty(subTables)){
				String[] arr = subTables.split(",");
				for (String tb : arr) {
					OnlCgformHead temp = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tb));
					if(temp==null) {
						continue;
					}
					List<OnlCgformField> subFieldList = this.fieldService.queryFormFields(temp.getId(),false);
					String sublinkField="",subLinkValue=null;
					for (OnlCgformField field : subFieldList) {
						if(oConvertUtils.isEmpty(field.getMainField())) {
							continue;
						}
						sublinkField = field.getDbFieldName();
						String mainField = field.getMainField();
						// 空指针 wcd?
						if(null == map.get(mainField)) {
							subLinkValue = map.get(mainField.toUpperCase()).toString();
						}else {
							subLinkValue = map.get(mainField).toString();
						}
					}

					List<Map<String, Object>> subList = this.fieldService.querySubFormData(subFieldList, tb, sublinkField, subLinkValue);
					if(subList==null || subList.size()==0) {
						map.put(tb, new String[] {});
					}else {
						map.put(tb, CgformUtil.toLowerCasePageList(subList));
					}
				}
			}

		}
		return map;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void editManyFormData(String code, JSONObject json) throws DBException, BusinessException {
		OnlCgformHead head = this.getById(code);
		if (head == null) {
			throw new DBException("数据库主表ID["+code+"]不存在");
		}
		//执行java增强 事件类型start
		String currButtonCode = "edit";
		this.executeEnhanceJava(currButtonCode,"start", head, json);
				
		String tbname = head.getTableName();
		//如果是tree则 新增时 赋值：是否子节点
		if("Y".equals(head.getIsTree())) {
			this.fieldService.editTreeFormData(code, tbname, json,head.getTreeIdField(), head.getTreeParentIdField());
		}else {
			fieldService.editFormData(code, tbname, json,false);
		}
		//主子表逻辑
		if(head.getTableType()==2) {
			String subTables = head.getSubTableStr();
			if(oConvertUtils.isNotEmpty(subTables)){
				String[] arr = subTables.split(",");
				for (String tb : arr) {
					OnlCgformHead temp = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tb));
					if(temp==null) {
						continue;
					}
					List<OnlCgformField> subFieldList = this.fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, temp.getId()));
					String sublinkField="",subLinkValue=null;
					for (OnlCgformField field : subFieldList) {
						if(oConvertUtils.isEmpty(field.getMainField())) {
							continue;
						}
						sublinkField = field.getDbFieldName();
						String mainField = field.getMainField();

						//update-begin-author:taoyan date:20190924 for:主子表关联字段取值bug
						if(json.get(mainField.toLowerCase())!=null){
							subLinkValue = json.getString(mainField.toLowerCase());
						}
						if(json.get(mainField.toUpperCase())!=null){
							subLinkValue = json.getString(mainField.toUpperCase());
						}
						//update-end-author:taoyan date:20190924 for:主子表关联字段取值bug
					}
					// 删除从表数据
					if(oConvertUtils.isEmpty(subLinkValue)) {
						continue;
					}
					fieldService.deleteAutoList(tb, sublinkField, subLinkValue);
					//新增数据
					JSONArray jsonArray = json.getJSONArray(tb);
					if(jsonArray==null || jsonArray.size()==0) {
						continue;
					}
					for(int i=0;i<jsonArray.size();i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						if(subLinkValue!=null) {
							jsonObject.put(sublinkField, subLinkValue);//设置外键值
						}
						this.fieldService.saveFormData(subFieldList, tb, jsonObject);
					}
				}
			}

		}
		
		//执行java增强 事件类型end
		this.executeEnhanceJava(currButtonCode,"end", head, json);
		//执行SQL增强
		this.executeEnhanceSql(currButtonCode,code, json);
		
	}



	@Override
	public int executeEnhanceJava(String buttonCode, String eventType,OnlCgformHead head,JSONObject json) throws BusinessException{
		LambdaQueryWrapper<OnlCgformEnhanceJava> query = new LambdaQueryWrapper<OnlCgformEnhanceJava>();
		query.eq(OnlCgformEnhanceJava::getActiveStatus, "1");
		query.eq(OnlCgformEnhanceJava::getButtonCode,buttonCode);
		query.eq(OnlCgformEnhanceJava::getCgformHeadId,head.getId());
		query.eq(OnlCgformEnhanceJava::getEvent, eventType);//start和end之分
		OnlCgformEnhanceJava enhance = this.onlCgformEnhanceJavaMapper.selectOne(query);
		Object obj = getEnhanceObject(enhance);
		if(obj!=null && obj instanceof CgformEnhanceJavaInter){
			CgformEnhanceJavaInter javaInter = (CgformEnhanceJavaInter) obj;
			return javaInter.execute(head.getTableName(),json);
		}
		return CgformUtil.OL_IMPORT_INSERT;
	}

	@Override
	public void executeEnhanceExport(OnlCgformHead head, List<Map<String, Object>> dataList) throws BusinessException {
		this.executeEnhanceList(head,CgformUtil.ENHANCE_EXPORT,dataList);
	}

	@Override
	public void executeEnhanceList(OnlCgformHead head, String buttonCode, List<Map<String, Object>> dataList) throws BusinessException {
		LambdaQueryWrapper<OnlCgformEnhanceJava> query = new LambdaQueryWrapper<OnlCgformEnhanceJava>();
		query.eq(OnlCgformEnhanceJava::getActiveStatus, CgformUtil.ENHANCE_ACTIVE);
		query.eq(OnlCgformEnhanceJava::getButtonCode,buttonCode);
		query.eq(OnlCgformEnhanceJava::getCgformHeadId,head.getId());
		List<OnlCgformEnhanceJava> enhances = this.onlCgformEnhanceJavaMapper.selectList(query);
		if(enhances!=null && enhances.size()>0) {
			Object obj = getEnhanceObject(enhances.get(0));
			if(obj!=null && obj instanceof CgformEnhanceJavaListInter){
				CgformEnhanceJavaListInter javaInter = (CgformEnhanceJavaListInter) obj;
				javaInter.execute(head.getTableName(),dataList);
			}

		}
	}

	/**
	 * 根据OnlCgformEnhanceJava对象获取CgformEnhanceJavaInter对象
	 * @param enhance
	 * @return
	 */
	private Object getEnhanceObject(OnlCgformEnhanceJava enhance){
		if(enhance!=null){
			String javaType = enhance.getCgJavaType();
			String javaValue = enhance.getCgJavaValue();
			if(oConvertUtils.isNotEmpty(javaValue)) {
				Object obj = null;
				if("class".equals(javaType)) {
					try {
						obj = MyClassLoader.getClassByScn(javaValue).newInstance();
					} catch (InstantiationException e) {
						log.error(e.getMessage(), e);
					} catch (IllegalAccessException e) {
						log.error(e.getMessage(), e);
					}
				}else if("spring".equals(javaType)){
					obj = SpringContextUtils.getBean(javaValue);
				}
				return obj;
			}
		}
		return null;
	}


	@Override
	public void executeEnhanceSql(String buttonCode, String formId, JSONObject json) {
		LambdaQueryWrapper<OnlCgformEnhanceSql> query = new LambdaQueryWrapper<OnlCgformEnhanceSql>();
		query.eq(OnlCgformEnhanceSql::getButtonCode,buttonCode);
		query.eq(OnlCgformEnhanceSql::getCgformHeadId,formId);
		OnlCgformEnhanceSql enhance = this.onlCgformEnhanceSqlMapper.selectOne(query);
		if(enhance!=null) {
			String sqls = CgformUtil.formateSQl(enhance.getCgbSql(), json);
			String [] arr = sqls.split(";");
			for(String sql:arr){
				if(sql == null || sql.toLowerCase().trim().equals("")){
					continue;
				}
				log.info(" online sql 增强： "+ sql);
				this.baseMapper.executeDDL(sql);
			}
		}
	}



	@Override
	public void executeCustomerButton(String buttonCode, String formId, String dataId) throws BusinessException {
		OnlCgformHead head = this.getById(formId);
		if(head==null) {
			throw new BusinessException("未找到表配置信息");
		}
		Map<String,Object> data = this.baseMapper.queryOneByTableNameAndId(CgformUtil.getRealTableName(head.getTableName()), dataId);
		
		JSONObject json = JSONObject.parseObject(JSON.toJSONString(data));
		//执行java增强 事件类型start
		this.executeEnhanceJava(buttonCode,"start", head, json);
		//执行sql 增强
		this.executeEnhanceSql(buttonCode, formId, json);
		//执行java 增强 事件类型end
		this.executeEnhanceJava(buttonCode,"end", head, json);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OnlCgformButton> queryValidButtonList(String headId) {
		LambdaQueryWrapper<OnlCgformButton> query = new LambdaQueryWrapper<OnlCgformButton>();
		query.eq(OnlCgformButton::getCgformHeadId,headId);
		query.eq(OnlCgformButton::getButtonStatus, "1");
		query.orderByAsc(OnlCgformButton::getOrderNum);
		return  this.onlCgformButtonMapper.selectList(query);
		
	}


	@Override
	public OnlCgformEnhanceJs queryEnhanceJs(String formId, String cgJsType) {
		LambdaQueryWrapper<OnlCgformEnhanceJs> query = new LambdaQueryWrapper<OnlCgformEnhanceJs>();
		query.eq(OnlCgformEnhanceJs::getCgformHeadId,formId);
		query.eq(OnlCgformEnhanceJs::getCgJsType, cgJsType);
		return this.onlCgformEnhanceJsMapper.selectOne(query);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteOneTableInfo(String formId, String dataId) throws BusinessException {
		OnlCgformHead head = this.getById(formId);
		if(head==null) {
			throw new BusinessException("未找到表配置信息");
		}
		//因为有复制视图的功能 所以需要加一个获取真实表名的方法
		String realTableName = CgformUtil.getRealTableName(head.getTableName());
		Map<String,Object> record = this.baseMapper.queryOneByTableNameAndId(realTableName, dataId);
		if(record==null) {
			throw new BusinessException("未找到数据信息");
		}
		String buttonCode = "delete";
		//执行java增强 事件类型start
		JSONObject json = JSONObject.parseObject(JSON.toJSONString(record));
		this.executeEnhanceJava(buttonCode,"start", head, json);

		//如果是树节点 需要判断上级节点状态
		this.updateParentNode(head, dataId);

		if(head.getTableType()==2){
			this.fieldService.deleteAutoListMainAndSub(head,dataId);
		}else{
			String sql = "delete from "+realTableName+" where id = '"+dataId+"'";
			this.baseMapper.deleteOne(sql);
		}

		this.executeEnhanceSql(buttonCode, formId, json);
		//执行java 增强 事件类型end
		this.executeEnhanceJava(buttonCode,"end", head, json);
	}

	/**
	 * 该方法 专门给非online功能 调用online表单组件用的
	 * @param head
	 * @return
	 */
	@Override
	public JSONObject queryFormItem(OnlCgformHead head) {
		//查询表有效字段
		List<OnlCgformField> fieldList = this.fieldService.queryAvailableFields(head.getId(), head.getTableName(), head.getTaskId(),false);

		List<String> disabledFieldNameList = new ArrayList<String>();
		if(oConvertUtils.isEmpty(head.getTaskId())){
			//查询表online被禁用字段
			List<String> disabledOnlineList = this.fieldService.queryDisabledFields(head.getTableName());
			if(disabledOnlineList!=null && disabledOnlineList.size()>0 && disabledOnlineList.get(0)!=null){
				disabledFieldNameList.addAll(disabledOnlineList);
			}
		}else{
			//查询表流程被禁用字段
			List<String> disabledFlowList = this.fieldService.queryDisabledFields(head.getTableName(),head.getTaskId());
			if(disabledFlowList!=null && disabledFlowList.size()>0 && disabledFlowList.get(0)!=null){
				disabledFieldNameList.addAll(disabledFlowList);
			}
		}

		//组装schema
		JSONObject schema = CgformUtil.getJsonSchemaByCgformFieldList(fieldList,disabledFieldNameList,null);
		if(head.getTableType()==2) {
			//主表
			String subStr = head.getSubTableStr();
			if(oConvertUtils.isNotEmpty(subStr)) {
				for (String tbname : subStr.split(",")) {
					OnlCgformHead tempTable = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tbname));
					if(tempTable==null) {
						continue;
					}
					//查询子表字段
					List<OnlCgformField> subFieldList = this.fieldService.queryAvailableFields(tempTable.getId(), tempTable.getTableName(), null,false);

					//查询被禁用字段
					List<String> subDisabledFieldNameList = this.fieldService.queryDisabledFields(tempTable.getTableName());

					JSONObject subJson = new JSONObject();
					if(1==tempTable.getRelationType()) {
						//one to one 
						subJson = CgformUtil.getJsonSchemaByCgformFieldList(subFieldList,subDisabledFieldNameList,null);
					}else {
						//one to many
						subJson.put("columns",  CgformUtil.getJEditableTableColumnsJson(subFieldList,subDisabledFieldNameList));
					}
					subJson.put("relationType", tempTable.getRelationType());// 0-1对多 1-1对1
					subJson.put("view", "tab");
					subJson.put("order",tempTable.getTabOrderNum());
					subJson.put("formTemplate", tempTable.getFormTemplate());
					subJson.put("describe", tempTable.getTableTxt());
					subJson.put("key", tempTable.getTableName());
					schema.getJSONObject("properties").put(tempTable.getTableName(), subJson);
				}
			}
		}
		//log.info("----动态表单获取JSON-SCHEMA>>"+schema.toJSONString());
		return schema;
	}

	@Override
	public List<String> generateCode(OnlGenerateModel model) throws Exception {
		TableVo tableVo = new TableVo();
		tableVo.setEntityName(model.getEntityName());
		tableVo.setEntityPackage(model.getEntityPackage());
		tableVo.setFtlDescription(model.getFtlDescription());
		tableVo.setTableName(model.getTableName());
		tableVo.setSearchFieldNum(-1);
		List<ColumnVo> columns = new ArrayList<ColumnVo>();
		List<ColumnVo> originalColumns = new ArrayList<ColumnVo>();
		initColumnVoList(model.getCode(),columns, originalColumns);
		//新增树形列表的所需参数
		OnlCgformHead tableConfig = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getId, model.getCode()));
		Map<String,String> extendParams = new HashMap<String,String>();
		extendParams.put("scroll",tableConfig.getScroll()==null?"0":tableConfig.getScroll().toString());
		if("Y".equals(tableConfig.getIsTree())) {
			extendParams.put("pidField", tableConfig.getTreeParentIdField());
			extendParams.put("hasChildren", tableConfig.getTreeIdField());
			extendParams.put("textField", tableConfig.getTreeFieldname());
		}
		tableVo.setExtendParams(extendParams);

		CgformEnum templateCgformEnum = CgformEnum.getCgformEnumByConfig(model.getJspMode());
		List<String> generateList = new CodeGenerateOne(tableVo, columns,originalColumns).generateCodeFile(model.getProjectPath(),templateCgformEnum.getTemplatePath(),templateCgformEnum.getStylePath());
		return generateList;
	}


	@Override
	public List<String> generateOneToMany(OnlGenerateModel model) throws Exception {
		MainTableVo mainTableVo = new MainTableVo();
		mainTableVo.setEntityName(model.getEntityName());
		mainTableVo.setEntityPackage(model.getEntityPackage());
		mainTableVo.setFtlDescription(model.getFtlDescription());
		mainTableVo.setTableName(model.getTableName());
		
		List<ColumnVo> mainColums = new ArrayList<ColumnVo>();
		List<ColumnVo> originalMainColumns = new ArrayList<ColumnVo>();
		initColumnVoList(model.getCode(),mainColums, originalMainColumns);
		
		List<OnlGenerateModel> subList = model.getSubList();
		List<SubTableVo> subTables = new ArrayList<SubTableVo>();
		for (OnlGenerateModel sub : subList) {
			OnlCgformHead subTableConfig = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, sub.getTableName()));
			if(subTableConfig==null) {
				continue;
			}
			SubTableVo subVo = new SubTableVo();
			subVo.setEntityName(sub.getEntityName());
			subVo.setEntityPackage(model.getEntityPackage());//子表和主表代码放在一个包里
			subVo.setTableName(sub.getTableName());
			subVo.setFtlDescription(sub.getFtlDescription());
			Integer manyOrone = subTableConfig.getRelationType();//映射关系  1一对一  0一对多
			subVo.setForeignRelationType(manyOrone==1?"1":"0");
			
			List<ColumnVo> columns = new ArrayList<ColumnVo>();
			List<ColumnVo> originalColumns = new ArrayList<ColumnVo>();
			OnlCgformField foreignKeys = initColumnVoList(subTableConfig.getId(),columns, originalColumns);
			if(foreignKeys==null) {
				continue;
			}
			subVo.setOriginalForeignKeys(new String[] {foreignKeys.getDbFieldName()});
			subVo.setForeignKeys(new String[] {foreignKeys.getDbFieldName()});
			subVo.setColums(columns);
			subVo.setOriginalColumns(originalColumns);
			subTables.add(subVo);
		}
		CgformEnum templateCgformEnum = CgformEnum.getCgformEnumByConfig(model.getJspMode());
		List<String> generateList = new CodeGenerateOneToMany(mainTableVo, mainColums, originalMainColumns, subTables).generateCodeFile(model.getProjectPath(),templateCgformEnum.getTemplatePath(),templateCgformEnum.getStylePath());
		return generateList;
	}
	
	/**
	  * 装载ColumnVo 集合
	 * @param columns
	 * @param originalColumns
	 * @param cgConfigId 配置表ID
	 * @return 返回外键的那个字段配置信息 主表可忽略
	 */
	@SuppressWarnings("unchecked")
	private OnlCgformField initColumnVoList(String cgConfigId,List<ColumnVo> columns,List<ColumnVo> originalColumns) {
		LambdaQueryWrapper<OnlCgformField> query = new LambdaQueryWrapper<OnlCgformField>();
		query.eq(OnlCgformField::getCgformHeadId,cgConfigId);
		query.orderByAsc(OnlCgformField::getOrderNum);
		List<OnlCgformField> fieldList = this.fieldService.list(query);
		OnlCgformField foreignKeys = null;
		for (OnlCgformField f : fieldList) {
			if(oConvertUtils.isNotEmpty(f.getMainTable())) {
				foreignKeys = f;
			}
			ColumnVo vo = new ColumnVo();
			vo.setFieldLength(f.getFieldLength());
			vo.setFieldHref(f.getFieldHref());
			vo.setFieldValidType(f.getFieldValidType());
			vo.setFieldDefault(f.getDbDefaultVal());
			vo.setFieldShowType(f.getFieldShowType());
			vo.setFieldOrderNum(f.getOrderNum());
			vo.setIsKey(f.getDbIsKey()==1?"Y":"N");
			vo.setIsShow(f.getIsShowForm()==1?"Y":"N");
			vo.setIsShowList(f.getIsShowList()==1?"Y":"N");
			vo.setIsQuery(f.getIsQuery()==1?"Y":"N");
			vo.setQueryMode(f.getQueryMode());
			vo.setDictField(f.getDictField());
			// TODO 字典注解不支持where条件 暂时去掉where
			if(oConvertUtils.isNotEmpty(f.getDictTable()) && f.getDictTable().indexOf("where")>0){
				vo.setDictTable(f.getDictTable().split("where")[0].trim());
			}else{
				vo.setDictTable(f.getDictTable());
			}
			vo.setDictText(f.getDictText());
			vo.setFieldDbName(f.getDbFieldName());
			vo.setFieldName(oConvertUtils.camelName(f.getDbFieldName()));
			vo.setFiledComment(f.getDbFieldTxt());
			vo.setFieldDbType(f.getDbType());
			vo.setFieldType(getFiledType(f.getDbType()));
			vo.setClassType(f.getFieldShowType());
			vo.setClassType_row(f.getFieldShowType());
			
			//update-begin-author:taoyan date:20190902 代码生成器 必填校验
			if(f.getDbIsNull()==0 || "*".equals(f.getFieldValidType()) || "1".equals(f.getFieldMustInput())) {
				vo.setNullable("N");
			}else {
				vo.setNullable("Y");
			}
			//update-end-author:taoyan date:20190902 代码生成器 必填校验
			
			originalColumns.add(vo);
			if(f.getIsShowForm()==1||f.getIsShowList()==1) {
				columns.add(vo);
			}
		}
		return foreignKeys;
	}
	
	
	/**
	 * 根据数据库类型获取java类型
	 * @param dbType
	 * @return
	 */
	private String getFiledType(String dbType) {
		dbType = dbType.toLowerCase();
		if(dbType.indexOf("int")>=0) {
			return "java.lang.Integer";
		}else if(dbType.indexOf("double")>=0) {
			return "java.lang.Double";
		}else if(dbType.indexOf("decimal")>=0) {
			return "java.math.BigDecimal";
		}else if(dbType.indexOf("date")>=0) {
			return "java.util.Date";
		}else {
			return "java.lang.String";
		}
	}



	@Override
	public void addCrazyFormData(String tbname, JSONObject json) throws DBException, UnsupportedEncodingException {
		OnlCgformHead head = this.getOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tbname));
		if (head == null) {
			throw new DBException("数据库主表["+tbname+"]不存在");
		}
		if(head.getTableType()==2) {
			//如果他是主表 则还需要保存子表的数据
			String subTables = head.getSubTableStr();
			if (subTables != null) {
				String[] arr = subTables.split(",");
				for (String tb : arr) {
					String subText = json.getString(CgformUtil.SUB_TABLE_PRE+tb);
					if(oConvertUtils.isEmpty(subText)) {
						continue;
					}
					JSONArray jsonArray = JSONArray.parseArray(URLDecoder.decode(subText, "UTF-8"));
					if(jsonArray==null || jsonArray.size()==0) {
						continue;
					}

					OnlCgformHead temp = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tb));
					if(temp==null) {
						continue;
					}

					List<OnlCgformField> subFieldList = this.fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, temp.getId()));
					//这里有一步非常重要 需要获取子表字段对应设置外键的那个字段然后赋值
					String sublinkField="",subLinkValue=null;
					for (OnlCgformField field : subFieldList) {
						if(oConvertUtils.isEmpty(field.getMainField())) {
							continue;
						}
						sublinkField = field.getDbFieldName();
						String mainField = field.getMainField();
						subLinkValue = json.getString(mainField);
					}

					for(int i=0;i<jsonArray.size();i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						if(subLinkValue!=null) {
							jsonObject.put(sublinkField, subLinkValue);//设置外键值
						}
						fieldService.executeInsertSQL(CgformUtil.getCrazyFormDataSaveSql(tb, subFieldList, jsonObject));
					}
				}
			}
		}
		this.fieldService.saveFormData(head.getId(), tbname, json, true);
	}



	@Override
	public void editCrazyFormData(String tbname, JSONObject json) throws DBException, UnsupportedEncodingException  {
		OnlCgformHead head = this.getOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tbname));
		if (head == null) {
			throw new DBException("数据库主表["+tbname+"]不存在");
		}
		if(head.getTableType()==2) {
			String subTables = head.getSubTableStr();
			String[] arr = subTables.split(",");
			for (String tb : arr) {
				OnlCgformHead temp = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getTableName, tb));
				if(temp==null) {
					continue;
				}
				List<OnlCgformField> subFieldList = this.fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, temp.getId()));
				String sublinkField="",subLinkValue=null;
				for (OnlCgformField field : subFieldList) {
					if(oConvertUtils.isEmpty(field.getMainField())) {
						continue;
					}
					sublinkField = field.getDbFieldName();
					String mainField = field.getMainField();
					subLinkValue = json.getString(mainField);
				}
				// 删除从表数据
				if(oConvertUtils.isEmpty(subLinkValue)) {
					continue;
				}
				fieldService.deleteAutoList(tb, sublinkField, subLinkValue);
				//新增数据
				String subText = json.getString(CgformUtil.SUB_TABLE_PRE+tb);
				if(oConvertUtils.isEmpty(subText)) {
					continue;
				}
				JSONArray jsonArray = JSONArray.parseArray(URLDecoder.decode(subText, "UTF-8"));
				if(jsonArray==null || jsonArray.size()==0) {
					continue;
				}
				for(int i=0;i<jsonArray.size();i++) {
					JSONObject jsonObject = jsonArray.getJSONObject(i);
					if(subLinkValue!=null) {
						jsonObject.put(sublinkField, subLinkValue);//设置外键值
					}
					fieldService.executeInsertSQL(CgformUtil.getCrazyFormDataSaveSql(tb, subFieldList, jsonObject));
				}	
			}
		}
		this.fieldService.editFormData(head.getId(), tbname, json, true);
		
	}



	@Override
	public Integer getMaxCopyVersion(String physicId) {
		Integer v = baseMapper.getMaxCopyVersion(physicId);
		return v==null?0:v;
	}


	@Override
	public void copyOnlineTableConfig(OnlCgformHead physicTable) throws Exception {
		String id = physicTable.getId();
		int maxVersion = this.getMaxCopyVersion(id);
		
		OnlCgformHead copy = new OnlCgformHead();
		String copyid = UUIDGenerator.generate();
		copy.setId(copyid);
		//复制表的属性值3
		copy.setPhysicId(id);
		copy.setCopyType(1);
		copy.setCopyVersion(++maxVersion);
		
		//原始表基本信息 12
		copy.setTableName(physicTable.getTableName()+CgformUtil.ONLINE_TABLE_SPLIT_STR+maxVersion);
		copy.setTableTxt(physicTable.getTableTxt());

		copy.setFormCategory(physicTable.getFormCategory());
		copy.setFormTemplate(physicTable.getFormTemplate());
		copy.setFormTemplateMobile(physicTable.getFormTemplateMobile());
		copy.setIdSequence(physicTable.getIdSequence());
		copy.setIdType(physicTable.getIdType());
		copy.setIsCheckbox(physicTable.getIsCheckbox());
		copy.setIsPage(physicTable.getIsPage());
		copy.setIsTree(physicTable.getIsTree());
		copy.setQueryMode(physicTable.getQueryMode());
		copy.setTableVersion(physicTable.getTableVersion());
		
		//复制表全设置为单表2
		copy.setTableType(1);
		copy.setIsDbSynch("N");
		
		//树表属性3
		copy.setTreeParentIdField(physicTable.getTreeParentIdField());
		copy.setTreeFieldname(physicTable.getTreeFieldname());
		copy.setTreeIdField(physicTable.getTreeIdField());
		
		//复制表全设置为单表 主子表需要设置的属性全设置为null 3
		copy.setRelationType(null);
		copy.setTabOrderNum(null);
		copy.setSubTableStr(null);

		//update-begin-author:taoyan date:20200411 for:新增字段 复制视图用到
		copy.setThemeTemplate(physicTable.getThemeTemplate());
		copy.setScroll(physicTable.getScroll());
		//update-end-author:taoyan date:20200411 for:新增字段 复制视图用到
		
		List<OnlCgformField> fieldList = this.fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, id));
		for (OnlCgformField f : fieldList) {
			OnlCgformField field = new OnlCgformField();
			field.setCgformHeadId(copyid);
			copyOnlCgformField(f, field);
			
			this.fieldService.save(field);
		}
		baseMapper.insert(copy);
	}

	


	@Override
	public void initCopyState(List<OnlCgformHead> headList) {
		List<String> idList = baseMapper.queryCopyPhysicId();
		for (OnlCgformHead temp : headList) {
			if(idList.contains(temp.getId())) {
				temp.setHascopy(1);
			}else {
				temp.setHascopy(0);
			}
		}
	}

	@Override
	public void deleteBatch(String ids, String flag) {
		String[] arr = ids.split(",");
		if(CgformUtil.REAL_DELETE.equals(flag)){
			for(String id:arr){
				try {
					this.deleteRecordAndTable(id);
				} catch (DBException e) {
					e.printStackTrace();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}else{
			this.removeByIds(Arrays.asList(arr));
		}
	}

	@Override
	public void updateParentNode(OnlCgformHead head, String dataId) {
		if(CgformUtil.STATUS_YES.equals(head.getIsTree())){
			String tbname = CgformUtil.getRealTableName(head.getTableName());
			String pidField = head.getTreeParentIdField();
			Map<String,Object> param = baseMapper.queryOneByTableNameAndId(tbname,dataId);
			String pid = null;
			if(param.get(pidField)!=null && !"0".equals(param.get(pidField))){
				pid = param.get(pidField).toString();
			}else if(param.get(pidField.toUpperCase())!=null && !"0".equals(param.get(pidField.toUpperCase()))){
				pid = param.get(pidField.toUpperCase()).toString();
			}
			if(pid!=null){
				Integer cnt = baseMapper.queryChildNode(tbname,pidField,pid);
				if(cnt==1){
					String hasChild = head.getTreeIdField();
					fieldService.updateTreeNodeNoChild(tbname,hasChild,pid);
				}
			}
		}
	}

	/**
	 * 同步复制表的列信息
	 * @param head
	 * @param fields
	 */
	private void handleCopyTableColumns(OnlCgformHead head,List<OnlCgformField> fields) {
		List<OnlCgformHead> copyList = this.list(new LambdaQueryWrapper<OnlCgformHead>().eq(OnlCgformHead::getPhysicId, head.getId()));
		
		if(copyList!=null && copyList.size()>0) {
			for (OnlCgformHead copy : copyList) {
				
				List<OnlCgformField> old_columns = fieldService.list(new LambdaQueryWrapper<OnlCgformField>().eq(OnlCgformField::getCgformHeadId, copy.getId()));
				if(old_columns==null || old_columns.size()==0) {
					//如果复制表不存在列 那么直接拿到前端传过来的列保存一下即可
					for (OnlCgformField temp : fields) {
						OnlCgformField col = new OnlCgformField();
						col.setCgformHeadId(copy.getId());
						copyOnlCgformField(temp, col);
						this.fieldService.save(col);
					}
				}else {
					//如果复制表存在列,比较不相同
					Map<String,Integer> oldMap = new HashMap<String,Integer>();
					for (OnlCgformField old : old_columns) {
						oldMap.put(old.getDbFieldName(), 1);
					}
					
					Map<String,Integer> newMap = new HashMap<String,Integer>();
					for (OnlCgformField temp : fields) {
						newMap.put(temp.getDbFieldName(), 1);
					}

					List<String> common_columns = new ArrayList<String>();
					
					List<String> new_columns = new ArrayList<String>();
					for (String fieldName : newMap.keySet()) {
						if(oldMap.get(fieldName)==null) {
							//新的集合里有，而老的集合里不存在这一列，说明这一列 是新增的
							new_columns.add(fieldName);
						}else{
							// 共有的字段 需要比较字段的数据库配置
							common_columns.add(fieldName);
						}
					}
					
					List<String> del_columns = new ArrayList<String>();
					for (String fieldName : oldMap.keySet()) {
						if(newMap.get(fieldName)==null) {
							//老的集合里有，新的集合里没有，说明这一列需要被删除
							del_columns.add(fieldName);
						}
					}
					
					
					//处理删除
					if(del_columns.size()>0) {
						for (OnlCgformField temp : old_columns) {
							if(del_columns.contains(temp.getDbFieldName())) {
								this.fieldService.removeById(temp.getId());
							}
						}
					}
					
					//处理新增
					if(new_columns.size()>0) {
						for (OnlCgformField temp : fields) {
							if(new_columns.contains(temp.getDbFieldName())) {
								OnlCgformField col = new OnlCgformField();
								col.setCgformHeadId(copy.getId());
								copyOnlCgformField(temp, col);
								this.fieldService.save(col);
							}
						}
					}

					//当原表字段 数据库配置被修改 复制表跟着改
					if(common_columns.size()>0){
						for (String fieldName : common_columns) {
							updateCopyColumn(fieldName,fields,old_columns);
						}
					}
					
				}
				
			}
			
		}
	}

	/**
	 * online 复制表 当原表字段 数据库配置被修改 复制表跟着改
	 * @param fieldName
	 * @param newCols
	 * @param copyCols
	 */
	private void updateCopyColumn(String fieldName,List<OnlCgformField> newCols,List<OnlCgformField> copyCols){

		OnlCgformField newCol = null;
		for (OnlCgformField temp : newCols) {
			if(fieldName.equals(temp.getDbFieldName())){
				newCol = temp;
			}
		}

		OnlCgformField copyCol = null;
		for (OnlCgformField temp : copyCols) {
			if(fieldName.equals(temp.getDbFieldName())){
				copyCol = temp;
			}
		}

		if(newCol!=null && copyCol!=null){
			boolean flag = false;
			if(!newCol.getDbType().equals(copyCol.getDbType())){
				copyCol.setDbType(newCol.getDbType());
				flag = true;
			}
			if(!newCol.getDbDefaultVal().equals(copyCol.getDbDefaultVal())){
				copyCol.setDbDefaultVal(newCol.getDbDefaultVal());
				flag = true;
			}
			if(newCol.getDbLength()!=copyCol.getDbLength()){
				copyCol.setDbLength(newCol.getDbLength());
				flag = true;
			}
			if(newCol.getDbIsNull()!=copyCol.getDbIsNull()){
				copyCol.setDbIsNull(newCol.getDbIsNull());
				flag = true;
			}
			if(flag){
				this.fieldService.updateById(copyCol);
			}
		}

	}
	
	/**
	 * 属性复制
	 * @param meta
	 * @param dest
	 */
	private void copyOnlCgformField(OnlCgformField meta,OnlCgformField dest) {
		dest.setDbDefaultVal(meta.getDbDefaultVal());
		dest.setDbFieldName(meta.getDbFieldName());
		dest.setDbFieldNameOld(meta.getDbFieldNameOld());
		dest.setDbFieldTxt(meta.getDbFieldTxt());
		dest.setDbIsKey(meta.getDbIsKey());
		dest.setDbIsNull(meta.getDbIsNull());
		dest.setDbLength(meta.getDbLength());
		dest.setDbPointLength(meta.getDbPointLength());
		dest.setDbType(meta.getDbType());
		dest.setDictField(meta.getDictField());
		dest.setDictTable(meta.getDictTable());
		dest.setDictText(meta.getDictText());
		dest.setFieldExtendJson(meta.getFieldExtendJson());
		dest.setFieldHref(meta.getFieldHref());
		dest.setFieldLength(meta.getFieldLength());
		
		dest.setFieldMustInput(meta.getFieldMustInput());
		dest.setFieldShowType(meta.getFieldShowType());
		dest.setFieldValidType(meta.getFieldValidType());
		dest.setFieldDefaultValue(meta.getFieldDefaultValue());
		dest.setIsQuery(meta.getIsQuery());
		dest.setIsShowForm(meta.getIsShowForm());
		dest.setIsShowList(meta.getIsShowList());
		dest.setMainField(null);
		dest.setMainTable(null);
		dest.setOrderNum(meta.getOrderNum());
		dest.setQueryMode(meta.getQueryMode());

		//update-begin-author:taoyan date:20200411 for:新增字段 复制视图用到
		dest.setIsReadOnly(meta.getIsReadOnly());
		dest.setSortFlag(meta.getSortFlag());
		dest.setQueryDefVal(meta.getQueryDefVal());
		dest.setQueryConfigFlag(meta.getQueryConfigFlag());
		dest.setQueryDictField(meta.getQueryDictField());
		dest.setQueryDictTable(meta.getQueryDictTable());
		dest.setQueryDictText(meta.getQueryDictText());
		dest.setQueryMustInput(meta.getQueryMustInput());
		dest.setQueryShowType(meta.getQueryShowType());
		dest.setQueryValidType(meta.getQueryValidType());
		dest.setConverter(meta.getConverter());
		//update-end-author:taoyan date:20200411 for:新增字段 复制视图用到
	}

	/**
	 * 保存编辑online表单字段的时候需要作些特殊处理
	 * @param field
	 */
	private void specialFieldHandler(OnlCgformField field){
		if("Text".equals(field.getDbType())||"Blob".equals(field.getDbType())){
			field.setDbLength(0);
			field.setDbPointLength(0);
		}
	}

}
